package influxdb

import (
	"encoding/json"
	"fmt"
	"github.com/cihub/seelog"
	"github.com/influxdata/influxdb/client/v2"
	"time"
)

const (
	Allflow = "allflow"
)

type DeviceFlow struct {
	DeviceId   string
	Time       time.Time
	ZoneId     string
	CountEnter int
	CountExit  int
	Status     int
}

func (c *Connect) SelectDeviceFlowByDeviceIdAndTime(table string, deviceId, startTime, endTime string) []*DeviceFlow {
	sql := fmt.Sprintf("SELECT * FROM %s where deviceId = '%s'and time>='%s' and time<='%s' order by time tz('%s');",
		table, deviceId, startTime, endTime, c.TimeZone)
	res, err := c.queryDB(sql)
	if err != nil {
		seelog.Error(err.Error())
	}
	return toDeviceFlow(res)
}

func (c *Connect) SelectDeviceFlowByStatus(table string, status int) []*DeviceFlow {
	sql := fmt.Sprintf("SELECT * FROM %s where status = %d order by time tz('%s');",
		table, status, c.TimeZone)
	res, err := c.queryDB(sql)
	if err != nil {
		seelog.Error(err.Error())
	}
	return toDeviceFlow(res)
}

func (c *Connect) InsertDeviceFlowBySendModel(sendMode *SendModel, status int) int {
	flow := make([]DeviceFlow, len(sendMode.InOutMetrics))
	for index, val := range sendMode.InOutMetrics {
		flow[index] = DeviceFlow{
			DeviceId:   sendMode.DeviceId,
			Time:       val.Time,
			ZoneId:     val.ZoneId,
			CountEnter: val.In,
			CountExit:  val.Out,
			Status:     status,
		}
	}
	return c.InsertDeviceFlow(flow, Allflow)
}

func (c *Connect) InsertDeviceFlow(flow []DeviceFlow, tableName string) int {
	var cPoint []*client.Point
	for _, value := range flow {
		tags := map[string]string{
			"deviceId": value.DeviceId,
			"zoneid":   value.ZoneId,
		}
		fields := map[string]interface{}{
			"countenter": value.CountEnter,
			"countexit":  value.CountExit,
			"status":     value.Status,
		}
		pt, err := client.NewPoint(tableName, tags, fields, value.Time)
		if err != nil {
			seelog.Error(err)
			return -1
		} else {
			cPoint = append(cPoint, pt)
		}
	}
	return c.insert(cPoint)
}

func toDeviceFlow(result []client.Result) []*DeviceFlow {
	var resFlow []*DeviceFlow
	var rarray []map[string]interface{}
	for _, res := range result {
		if res.Err == "" {
			for _, row := range res.Series {
				cloumns := row.Columns
				for _, values := range row.Values {
					rmap := make(map[string]interface{}, len(cloumns))
					for index, va := range values {
						rmap[cloumns[index]] = va
					}
					rarray = append(rarray, rmap)
				}
			}
		} else {
			seelog.Error(res.Err)
		}
	}
	rjson, err := json.Marshal(rarray)
	if err != nil {
		seelog.Error(err)
	}
	json.Unmarshal(rjson, &resFlow)
	return resFlow
}
